package com.enjoy.concurrent.ch8;

import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
@SuppressWarnings("unchecked")
public class PendingJobPool {
    public static final int THREAD_COUNT = Runtime.getRuntime().availableProcessors();

    private static BlockingQueue<Runnable> taskQueue = new ArrayBlockingQueue<>(1000);

    private static ExecutorService taskExecutor = new ThreadPoolExecutor(THREAD_COUNT, THREAD_COUNT, 60, TimeUnit.SECONDS, taskQueue);

    private static Map<String, JobInfo<?>> jobInfoMap = new ConcurrentHashMap<>();

    private PendingJobPool() {
    }

    private static class JobPoolHolder {
        public static PendingJobPool pool = new PendingJobPool();
    }

    public static PendingJobPool getInstance() {
        return JobPoolHolder.pool;
    }

    private static class PendingTask<R, T> implements Runnable {

        private JobInfo<R> jobInfo;
        private T processData;

        public PendingTask(JobInfo<R> jobInfo, T processData) {
            this.jobInfo = jobInfo;
            this.processData = processData;
        }

        @Override
        public void run() {
            R r = null;
            ITaskProcessor<R, T> taskProcessor = (ITaskProcessor<R, T>) jobInfo.getTaskProcessor();

            TaskResult<R> taskResult = null;
            try {
                taskResult = taskProcessor.taskExecute(processData);
                if (taskResult == null) {
                    taskResult = new TaskResult<>(TaskResultType.EXCEPTION, r, "result is null");
                }
                if (taskResult.getResultType() == null) {
                    if (taskResult.getReason() == null) {
                        new TaskResult<>(TaskResultType.EXCEPTION, r, "reason is null");
                    } else {
                        new TaskResult<>(TaskResultType.EXCEPTION, r, "reason is null " + taskResult.getReason());
                    }
                }
            } catch (Exception e) {
                taskResult = new TaskResult<>(TaskResultType.EXCEPTION, r, e.getMessage());
            } finally {
                jobInfo.addTaskResult(taskResult);
            }
        }
    }

    // 调用者提交工作中的任务
    public <R, T> void putTask(String jobName, T t) {
        JobInfo<R> jobInfo = getJob(jobName);
        PendingTask<R, T> task = new PendingTask<>(jobInfo, t);
        taskExecutor.execute(task);
    }

    //调用者注册工作
    public <R> void registerJob(String jobName, int jobLength, ITaskProcessor<R, ?> taskProcessor, long expireTime) {
        JobInfo<R> jobInfo = new JobInfo<R>(jobName, jobLength, taskProcessor, expireTime);
        if (jobInfoMap.putIfAbsent(jobName, jobInfo) != null) {
            throw new RuntimeException(jobName + " 已经注册");
        }
    }

    public List<?> getTaskDetail(String jobName) {
        JobInfo<?> job = getJob(jobName);
        return job.getTaskDetail();
    }

    private <R> JobInfo<R> getJob(String jobName) {
        JobInfo<R> jobInfo = (JobInfo<R>) jobInfoMap.get(jobName);
        if (jobInfo == null) {
            throw new RuntimeException(jobName + "非法任务");
        }
        return jobInfo;
    }

    public static BlockingQueue<Runnable> getTaskQueue() {
        return taskQueue;
    }

    public static void setTaskQueue(BlockingQueue<Runnable> taskQueue) {
        PendingJobPool.taskQueue = taskQueue;
    }

    public static ExecutorService getTaskExecutor() {
        return taskExecutor;
    }

    public static void setTaskExecutor(ExecutorService taskExecutor) {
        PendingJobPool.taskExecutor = taskExecutor;
    }

    public static Map<String, JobInfo<?>> getJobInfoMap() {
        return jobInfoMap;
    }

    public static void setJobInfoMap(Map<String, JobInfo<?>> jobInfoMap) {
        PendingJobPool.jobInfoMap = jobInfoMap;
    }
}
